using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using Abp.Linq.Extensions;
using System.Collections.Generic;
using System.Threading.Tasks;
using Abp.Domain.Repositories;
using Precise.Products.Exporting;
using Precise.Products.Dtos;
using Precise.Dto;
using Abp.Application.Services.Dto;
using Precise.Authorization;
using Abp.Extensions;
using Abp.Authorization;
using Microsoft.EntityFrameworkCore;

namespace Precise.Products
{
    [AbpAuthorize(AppPermissions.Pages_GoodsImag)]
    public class GoodsImagAppService : PreciseAppServiceBase, IGoodsImagAppService
    {
        private readonly IRepository<GoodsImage, long> _goodsImageRepository;
        private readonly IGoodsImagExcelExporter _goodsImagExcelExporter;
        private readonly IRepository<Goods, long> _goodsRepository;


        public GoodsImagAppService(IRepository<GoodsImage, long> goodsImageRepository, IGoodsImagExcelExporter goodsImagExcelExporter, IRepository<Goods, long> goodsRepository)
        {
            _goodsImageRepository = goodsImageRepository;
            _goodsImagExcelExporter = goodsImagExcelExporter;
            _goodsRepository = goodsRepository;

        }

        public async Task<PagedResultDto<GetGoodsImageForView>> GetAll(GetAllGoodsImagInput input)
        {

            var filteredGoodsImag = _goodsImageRepository.GetAll()
                        .WhereIf(!string.IsNullOrWhiteSpace(input.Filter), e => false || e.Path.Contains(input.Filter));


            var query = (from o in filteredGoodsImag
                         join o1 in _goodsRepository.GetAll() on o.GoodsId equals o1.Id into j1
                         from s1 in j1.DefaultIfEmpty()

                         select new GetGoodsImageForView()
                         {
                             GoodsImage = ObjectMapper.Map<GoodsImageDto>(o),
                             GoodsName = s1 == null ? "" : s1.Name.ToString()
                         })
                        .WhereIf(!string.IsNullOrWhiteSpace(input.GoodsName), e => e.GoodsName.ToLower() == input.GoodsName.ToLower().Trim());

            var totalCount = await query.CountAsync();

            var goodsImag = await query
                .OrderBy(input.Sorting ?? "goodsImage.id asc")
                .PageBy(input)
                .ToListAsync();

            return new PagedResultDto<GetGoodsImageForView>(
                totalCount,
                goodsImag
            );
        }

        [AbpAuthorize(AppPermissions.Pages_GoodsImag_Edit)]
        public async Task<GetGoodsImageForEditOutput> GetGoodsImageForEdit(EntityDto<long> input)
        {
            var goodsImage = await _goodsImageRepository.FirstOrDefaultAsync(input.Id);

            var output = new GetGoodsImageForEditOutput { GoodsImage = ObjectMapper.Map<CreateOrEditGoodsImageDto>(goodsImage) };

            var goods = await _goodsRepository.FirstOrDefaultAsync(output.GoodsImage.GoodsId);
            output.GoodsName = goods.Name.ToString();

            return output;
        }

        public async Task CreateOrEdit(CreateOrEditGoodsImageDto input)
        {
            if (input.Id == null)
            {
                await Create(input);
            }
            else
            {
                await Update(input);
            }
        }

        [AbpAuthorize(AppPermissions.Pages_GoodsImag_Create)]
        private async Task Create(CreateOrEditGoodsImageDto input)
        {
            var goodsImage = ObjectMapper.Map<GoodsImage>(input);


            if (AbpSession.TenantId != null)
            {
                goodsImage.TenantId = (int)AbpSession.TenantId;
            }


            await _goodsImageRepository.InsertAsync(goodsImage);
        }

        [AbpAuthorize(AppPermissions.Pages_GoodsImag_Edit)]
        private async Task Update(CreateOrEditGoodsImageDto input)
        {
            var goodsImage = await _goodsImageRepository.FirstOrDefaultAsync((long)input.Id);
            ObjectMapper.Map(input, goodsImage);
        }

        [AbpAuthorize(AppPermissions.Pages_GoodsImag_Delete)]
        public async Task Delete(EntityDto<long> input)
        {
            await _goodsImageRepository.DeleteAsync(input.Id);
        }

        public async Task<FileDto> GetGoodsImagToExcel(GetAllGoodsImagForExcelInput input)
        {

            var filteredGoodsImag = _goodsImageRepository.GetAll()
                        .WhereIf(!string.IsNullOrWhiteSpace(input.Filter), e => false || e.Path.Contains(input.Filter));


            var query = (from o in filteredGoodsImag
                         join o1 in _goodsRepository.GetAll() on o.GoodsId equals o1.Id into j1
                         from s1 in j1.DefaultIfEmpty()

                         select new GetGoodsImageForView()
                         {
                             GoodsImage = ObjectMapper.Map<GoodsImageDto>(o),
                             GoodsName = s1 == null ? "" : s1.Name.ToString()
                         })
                        .WhereIf(!string.IsNullOrWhiteSpace(input.GoodsName), e => e.GoodsName.ToLower() == input.GoodsName.ToLower().Trim());


            var goodsImageListDtos = await query.ToListAsync();

            return _goodsImagExcelExporter.ExportToFile(goodsImageListDtos);
        }



        [AbpAuthorize(AppPermissions.Pages_GoodsImag)]
        public async Task<PagedResultDto<GoodsLookupTableDto>> GetAllGoodsForLookupTable(GetAllForLookupTableInput input)
        {
            var query = _goodsRepository.GetAll().WhereIf(
                   !string.IsNullOrWhiteSpace(input.Filter),
                  e => e.Name.ToString().Contains(input.Filter)
               );

            var totalCount = await query.CountAsync();

            var goodsList = await query
                .PageBy(input)
                .ToListAsync();

            var lookupTableDtoList = new List<GoodsLookupTableDto>();
            foreach (var goods in goodsList)
            {
                lookupTableDtoList.Add(new GoodsLookupTableDto
                {
                    Id = goods.Id,
                    DisplayName = goods.Name?.ToString()
                });
            }

            return new PagedResultDto<GoodsLookupTableDto>(
                totalCount,
                lookupTableDtoList
            );
        }
    }
}